/**
  * @description: g2--堆叠柱状图
  * @author: hj
  * @update: hj(2020-01-14)
  */

import React, {Component} from 'react';
import G2 from '@antv/g2';
import DataSet from '@antv/data-set';
import {getMediaById} from '@/service/Api/Chart';
import { observer,inject,Provider } from 'mobx-react';

let barStackTimer;

 
@inject('chartStore') 
@observer
class BarStackChart extends Component {
    constructor(props) {
        super(props);
        this.state = {
            params: [],
            data: [],
            forceFit: true, //forceFit自动试用宽度，默认false
            width: this.props.data.width ? this.props.data.width : '100%',   // 固定宽度    当自适应宽度开启，此功能失效
            height: this.props.data.height ? this.props.data.height - 50 : '100%',
            condition: this.props.data.condition ? this.props.data.condition : '',
            pageFlag: this.props.data.pageFlag ? this.props.data.pageFlag : '',
            nofirst: this.props.data.nofirst ? this.props.data.nofirst : '',
            color: [],
            fields: [],
            xAxis: "",
            title: '',
            chartId: this.props.data.chartId,
            id: this.props.data.componentId,
            chartData: [],
            axisArr: {},
            haveData: false,
            legend: 'top',
            padding: '',

            dataNull: false, // 暂无数据

            // 全局变量
            mainData: [], // 操作组件可操作数据
            mainName: '', // 操作组件可操作当前维度
            mainFlag: false, // 是否是操作组件

            pageInitFlag: true,
            affectName: '',
            requireCondition: '',
        };
    };


    componentWillMount() { //初始化
        const _this = this;
        
        // 预览界面
        if (_this.state.pageFlag == 'preview') {
            // 判断当前组件是否是可操作组件
            const { globalData } = _this.props.chartStore;
            if (globalData.slice().length > 0) {
                globalData.slice().map((item,index) => {
                    if (item.affect == _this.state.chartId) { // 可操作组件
                        let affectName = item.affectDimension;
                        _this.setState({
                            mainFlag: true,
                            mainName: affectName
                        })
                    }
                })
            }

            _this.interfaceRequest(_this.state.chartId,_this.state.condition);
        } else { // 配置面板
            if (_this.state.nofirst == 'nofirst') {
                _this.saveHandleData();
            } else {
                _this.interfaceRequest(_this.state.chartId,_this.state.condition);
            }
        }
    }

    // 钩子函数--组件挂载完成后
    componentDidMount() { //初始化
        this.setState({
            haveData: true
        })
    }
    // 接收父组件的数据改变
    componentWillReceiveProps = (nextProps) => {
        const _this = this;
        const { globalData, affectId } = _this.props.chartStore;

        // 预览界面---判断是否是变化组件
        if (nextProps.data.pageFlag == 'preview') {
            if (nextProps.data.condition != _this.state.requireCondition && globalData.slice().length > 0) {
                globalData.slice().map((item,index) => {
                    if (item.affect == affectId && item.require == nextProps.data.chartId) { // 联动组件
                        _this.setState({
                            pageInitFlag: false
                        })
                        let condition = {};
                        Object.keys(_this.state.requireCondition).forEach(function(keys){
                            condition[keys] = keys == item.requireDimension ? nextProps.data.condition[keys] : _this.state.requireCondition[keys];
                        })
                        _this.interfaceRequest(nextProps.data.chartId,condition);
                    }
                })
            }
        }
    }

    // 数据接口请求
    interfaceRequest = (chartId,condition) => {
        this.setState({
            requireCondition: condition,
        });

        let data = {
            charId: chartId,
            condition: condition
        };
        this.getMediaById(data);
    }

    // 数据存储刷新
    saveHandleData = () => {
        const { chartArrData } = this.props.chartStore;
        if (chartArrData.slice().length > 0) {
            chartArrData.slice().map((item) => {
                if (item.id == this.state.chartId) {
                    this.setState({
                        haveData: false
                    },function() {
                        // 数据处理
                        this.handleData(item.data);
                    })
                }
            })
        }
    }


    async getMediaById(data) {
        const res = await getMediaById(data);
        if (res.data && res.data.code === 0) {
            let str = res.data;
            if (str.data && str.data.data && str.data.data.length > 0) {
                // 存储图例原始数据
                const { saveChartData } = this.props.chartStore;
                let oldData = {
                    id: this.state.chartId,
                    data: str.data.data
                }
                saveChartData(oldData);

                // 数据处理
                this.handleData(str.data.data);
            } else {
                this.setState({
                    dataNull: true
                })
            }
        } else {
            this.setState({
                dataNull: true
            })
        }
    }
    // 数据处理
    handleData = (storeAllData) => {
        let storeData = storeAllData[0];
        this.setState({
            dataNull: true
        })

        // 非预览界面
        if (this.state.pageFlag != 'preview') {
            // 存储可操作组件数据
            if (storeData.affect && storeData.affect.length > 0) {
                let obj = {
                    id: this.state.chartId,
                    label: storeData.title,
                    dimensionData: []
                }
                const { saveAffectData } = this.props.chartStore;

                let dimensionData = [];
                storeData.affect.slice().map((item,index) => {
                    dimensionData.push(item);
                })
                obj.dimensionData = dimensionData;
                saveAffectData(obj);
            }
            // 存储联动组件数据
            if (storeData.requires && storeData.requires.length > 0) {
                let obj = {
                    id: this.state.chartId,
                    label: storeData.title,
                    dimensionData: []
                }
                const { saveRequireData } = this.props.chartStore;

                let dimensionData = [];
                storeData.requires.slice().map((item,index) => {
                    dimensionData.push(item);
                })
                obj.dimensionData = dimensionData;
                saveRequireData(obj);
            }
        }

        // 页面初始化
        if (this.state.pageInitFlag) {
            if (storeData.affect &&  storeData.affect.length > 0) {
                this.setState({
                    affectName: storeData.affect[0]
                });
            }
            // 获取选择项
            if (storeData.conditionValues) {
                let selectData = storeData.conditionValues[storeData.affect[0]] ? storeData.conditionValues[storeData.affect[0]] : [];
                this.setState({
                    mainData: selectData
                });
            }
        }


        // 组装当前图例的维度和度量
        let xyArr = [];
        let axisArr = [];
        axisArr.push(storeData.xAxis);
        let axisName = axisArr.concat(storeData.fields.slice());
      
        axisName.map((item,index) => {
            Object.keys(storeData.columnMaps).forEach(function(key){
                if (key == item) {
                    let keyName = (index == 0) ? 'time' : key;
                    xyArr.push({
                        key: keyName,
                        label: storeData.columnMaps[key]
                    })
                }
            });
        })

        let newData = [];
        if (storeData.data.length > 0) {
            storeData.data.map((item,index) => {
                let obj = {};
                Object.keys(item).forEach(function(key){
                    xyArr.map((v,i) => {
                        if (v.key == key) {
                            let keyName = (key == axisName[0]) ? 'time' : v.label;
                            obj[keyName] = item[key];
                        } else if (v.key == 'time') {
                            let keyName = (key == axisName[0]) ? 'time' : v.label;
                            obj[keyName] = item[key];
                        }
                    })
                });
                newData.push(obj);
            })

            this.setState({
                dataNull: false
            })
        }
        
        this.setState({
            title: storeData.title,
            chartData: newData,
            axisArr: xyArr,
            color: storeData.colors.split(","),
            haveData: true,
            legend: storeData.legend ? storeData.legend : 'top',
            padding: storeData.padding && storeData.padding != '' ? storeData.padding.split(',') : [40, 40, 40, 50], // 默认legend在top位置,
        })
    }

    // 改变全局变量
    onGlobalVariable = (val) => {
        const { saveAffectId } = this.props.chartStore;
        saveAffectId(this.state.chartId);
        this.props.onGlobalVariable(val);
    }




    render() {
        const _this = this;
        let Layer = this.props.layer;


        let chartData = this.state.chartData;
        let haveData = this.state.haveData;
        let axisArr = this.state.axisArr;

        if (haveData) {
            document.getElementById('chart_'+this.state.id+'_'+this.state.chartId).innerHTML = '';
        }
        if (haveData && chartData.length > 0) {
            document.getElementById('chart_'+this.state.id+'_'+this.state.chartId).innerHTML = '';
            _this.setState({
                haveData: false
            });

            let x = axisArr[0].key;
            let y1 = axisArr[1].label;
            axisArr.splice(0,1);
            let fieldsArr = axisArr.map((item,index) => {
                return item.label;
            });

            let data = chartData;

            let ds = new DataSet();
            let dv = ds.createView().source(data);
            dv.transform({
                type: 'fold',
                fields: fieldsArr, // 展开字段集
                key: 'key', // key字段
                value: 'value' // value字段
            });

            let chart = new G2.Chart({
                container: 'chart_' + this.state.id + '_' + this.state.chartId,
                forceFit: true,
                height: _this.state.height,
                padding: _this.state.padding,
            });
            chart.source(dv);
            chart.axis(x, {
                position: 'bottom', // 设置坐标轴的显示位置，可取值 top bottom left right
                line: {
                    lineWidth: 1, // 设置线的宽度
                    stroke: '#536f8e' //  设置线的颜色
                }, // 设置坐标轴线的样式，如果值为 null，则不显示坐标轴线 图形属性
                label: {
                    // offset: 5, // 数值，设置坐标轴文本 label 距离坐标轴线的距离
                    // offsetX: 0, // 在 offset 的基础上 x 方向的偏移量
                    // offsetY: 0, // 在 offset 的基础上 y 方向的偏移量
                    // // 设置文本的显示样式，还可以是个回调函数，回调函数的参数为该坐标轴对应字段的数值
                    // rotate: 0, // 注意，旋转角度的配置不再在 textStyle 里配置
                    textStyle: {
                        textAlign: 'center', // 文本对齐方向，可取值为： start center end
                        fill: '#24C6F5', // 文本的颜色
                        fontSize: '12', // 文本大小
                        // textBaseline: 'top' // 文本基准线，可取 top middle bottom，默认为middle
                    }
                },
                title: null, // 坐标轴标题设置，如果值为 null，则不显示标题
                // tickLine: {
                //     lineWidth: 1, // 刻度线宽
                //     stroke: '#536f8e', // 刻度线的颜色
                //     length: -5, // 刻度线的长度
                // }, // 坐标轴刻度线配置
            });
            chart.axis('value', {
                tickInterval: 20,
                position: 'left', // 设置坐标轴的显示位置，可取值 top bottom left right
                line: {
                    lineWidth: 1, // 设置线的宽度
                    stroke: '#536f8e' //  设置线的颜色
                }, // 设置坐标轴线的样式，如果值为 null，则不显示坐标轴线 图形属性
                label: {
                    offset: 0, // 数值，设置坐标轴文本 label 距离坐标轴线的距离
                    offsetX: -10, // 在 offset 的基础上 x 方向的偏移量
                    offsetY: 0, // 在 offset 的基础上 y 方向的偏移量
                    // 设置文本的显示样式，还可以是个回调函数，回调函数的参数为该坐标轴对应字段的数值
                    textStyle: {
                        textAlign: 'end', // 文本对齐方向，可取值为： start center end
                        fill: '#24C6F5', // 文本的颜色
                        fontSize: '12', // 文本大小
                    }
                },
                title: null, // 坐标轴标题设置，如果值为 null，则不显示标题
                tickLine: null,
                grid: {
                    align: 'center', // 声明网格顶点从两个刻度中间开始，默认从刻度点开始
                    type: 'line', // 声明网格的类型，line 表示线，polygon 表示矩形框
                    // 当网格类型 type 为 line 时，使用 lineStyle 设置样式
                    lineStyle: {
                      stroke: '#21355f', // 网格线的颜色
                      lineWidth: 1, // 网格线的粗细
                      lineDash: [4, 4 ] // 网格线的虚线配置，第一个参数描述虚线的实部占多少像素，第二个参数描述虚线的虚部占多少像素
                    },
                    hideFirstLine: true, // 是否隐藏第一条网格线，默认为 false
                    hideLastLine: true, // 是否隐藏最后一条网格线，默认为 false
                }, // 坐标轴栅格线的配置信息，默认只有左边的坐标轴带有栅格线，null 为不显示。
            });
            chart.legend({
                // offsetY: -5, // 图例 Y 方向的偏移值，数值类型，数值单位为 'px'，默认值为 0。
                // itemGap: 10, // 表示图例每项之间的间距，如果是水平排布则为左右间距，如果是竖直排布则为上下间距。
                position: this.state.legend, // 图例的显示位置，有 'top','left','right','bottom'四种位置，默认是'right'。
                textStyle: {
                    fill: '#24C6F5', // 文本的颜色
                    fontSize: '12', // 文本大小
                }
            });
            chart.tooltip({
                triggerOn: 'click',
                useHtml:true,
                htmlContent:function(title,items){
                    let itemContnt = '';
                    items.map((v,i) => {
                        itemContnt += '<li style="display: block;" style="padding-left: 5px;">'
                                    + '<span style="background-color:'+  v.color +';width: 6px;height: 6px;display: inline-block;border-radius: 3px;margin-right: 3px;" class="g2-tooltip-marker"></span>' 
                                    + '<span style="color: #BDE9FF;">'+  v.name +'： </span>'
                                    + '<span style="color: '+  v.color +';">'+  v.value +'</span>'
                            + '</li>';
                    })
                    return '<div class="g2-tooltip" style="padding: 5px 15px 15px 15px;position: absolute;left: '+ items[0].x +';top:'+  items[0].y +';">'
                            + '<div class="g2-tooltip-title" style="margin-bottom: 4px;color: #6AEBFC;margin-top: 7px;">'+ title +'</div>'
                            + '<ul class="g2-tooltip-list">'
                                + itemContnt
                            + '</ul>'
                        + '</div>';
                }
            });

            chart.intervalStack().position('time*value').color('key',this.state.color);
            chart.render();

            // tooltip自动轮播
            setTimeout(() => {
                let num = 0;
                //去掉定时器的方法  
                barStackTimer = barStackTimer + this.state.id+'_'+this.state.chartId; 
                if (barStackTimer) window.clearInterval(barStackTimer);

                barStackTimer = window.setInterval(function() {
                    if (num == data.length) {
                        num = 0;
                    }
                
                    let point = chart.getXY({time: data[num].time, value: data[num][y1]});
                    chart.showTooltip(point);
                    num++;
                },2000)
            }, 10);
        }


        return (
            <div id={this.state.id + '_' + this.state.chartId} style={{zIndex: 99,width: this.state.width, height: this.state.height,padding: '40px 2% 10px 2%'}}>
                <Layer width={this.state.width} title={this.state.title} chartId={this.state.chartId} choiceData={this.state.mainData} onGlobalVariable={this.onGlobalVariable}></Layer>
                <div id={'chart_' + this.state.id + '_' + this.state.chartId}></div>
                { this.state.dataNull && <p style={{height: this.state.height,lineHeight: this.state.height+'px',color: '#fff',textAlign: 'center'}}> 暂无数据 </p>}
            </div>
        )
    }


}

export default BarStackChart;
